﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using Common.Utilities.Dispatcher;
using WindowsUserControl.Codes;

namespace Workflows.Components.Rules
{
    /// <summary>
    /// 
    /// </summary>
    public partial class CodeRuleEditor : Form, IComponentEditor 
    {
        #region fields
        private CodeSnippetEditor _CodeFragment = null;
        private object _ActivityNode;
        private CodeRuleComponent _CodeRuleComponent;
        #endregion

        /// <summary>
        /// 
        /// </summary>
        public CodeRuleEditor()
        {
            InitializeComponent();
        }

        private void CodeRuleEditor_Load(object sender, EventArgs e)
        {
            this.grp_Code.Controls.Clear();
            this._CodeFragment = new CodeSnippetEditor();
            this.grp_Code.Controls.Add(this._CodeFragment);
            this._CodeFragment.Dock = DockStyle.Fill;
        }

        #region IComponentEditor Members

        public event UpdateComponentSettings UpdateComponentSettingEvent;

        public object OwnerActivityNode
        {
            get { return _ActivityNode; }
            set { _ActivityNode = value; }
        }

        public Type WorkflowComponentType
        {
            get { return typeof (CodeRuleComponent); }
        }

        public void LoadSettings(GlobalVariable[] globalVars, WorkflowComponentBase[] fromComponents,
                                 object activityNode, WorkflowComponentBase wfComponent)
        {
            this._ActivityNode = activityNode;
            this._CodeRuleComponent = (CodeRuleComponent) wfComponent;
            List<string> externalAssemblies = new List<string>();
            this.txt_AssemblyFileName.Text = this._CodeRuleComponent.InputAssemblyName;
            this.cbo_InputType.Items.Clear();

            if (!string.IsNullOrEmpty(this._CodeRuleComponent.InputAssemblyName))
            {
                this.ck_Gac.Checked = false;
                string binFolderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                string assemblyFilePath = Path.Combine(binFolderPath, this._CodeRuleComponent.InputAssemblyName);
                Assembly assembly = Assembly.LoadFrom(assemblyFilePath);
                Type[] types = assembly.GetTypes();
                foreach (Type type in types)
                {
                    this.cbo_InputType.Items.Add(type.FullName);
                }
                externalAssemblies.Add(assemblyFilePath);
                
            }
            else
            {
                this.ck_Gac.Checked = true;
                Assembly sysAssembly = typeof (string).Assembly;
                Type[] types = sysAssembly.GetTypes();
                foreach (Type type in types)
                {
                    this.cbo_InputType.Items.Add(type.FullName);
                }
            }
            if (this.cbo_InputType.Items.Count > 0 && (!string.IsNullOrEmpty(this._CodeRuleComponent.InputTypeFullName)))
            {
                for (int i = 0; i < this.cbo_InputType.Items.Count; i++)
                {
                    if (this.cbo_InputType.Items[i].ToString() == this._CodeRuleComponent.InputTypeFullName)
                    {
                        this.cbo_InputType.SelectedIndex = i;
                        break;
                    }
                }
            }

            this.txt_RuleName.Text = this._CodeRuleComponent.RuleName;
            if (this.cbo_RuleCategories.Items.Count > 0 && (!string.IsNullOrEmpty(this._CodeRuleComponent.CategoryName)))
            {
                for (int i = 0; i < this.cbo_RuleCategories.Items.Count; i++)
                {
                    if (this.cbo_RuleCategories.Items[i].ToString() == this._CodeRuleComponent.CategoryName)
                    {
                        this.cbo_RuleCategories.SelectedIndex = i;
                        break;
                    }
                }
            }
            else
            {
                this.cbo_RuleCategories.Text = this._CodeRuleComponent.CategoryName;
            }

            string codeHeader = CodeRuleWorker.GenerateHeaderCode(this._CodeRuleComponent);
            string codeFooter = CodeRuleWorker.GenerateFooterCode();
            if(externalAssemblies.Count==1)
            {
                this._CodeFragment.ExternalAssembly = externalAssemblies[0];
            }
            this._CodeFragment.HeaderCode = codeHeader;
            this._CodeFragment.FooterCode = codeFooter;
            if (string.IsNullOrEmpty(this._CodeRuleComponent.Code))
            {
                this._CodeFragment.CodeSnippet = "// enter user code to evaluate input";
            }
            else
            {
                this._CodeFragment.CodeSnippet = this._CodeRuleComponent.Code;
            }
        }

        public void SaveSettings()
        {
            this._CodeRuleComponent.RuleName = this.txt_RuleName.Text;
            this._CodeRuleComponent.CategoryName = this.cbo_RuleCategories.Text;
            this._CodeRuleComponent.InputAssemblyName = this.txt_AssemblyFileName.Text;
            this._CodeRuleComponent.InputTypeFullName = this.cbo_InputType.Text;
            this._CodeRuleComponent.Code = this._CodeFragment.CodeSnippet;
            
            if(this.ck_Gac.Checked)
            {
                this._CodeRuleComponent.InputAssemblyName = string.Empty;
            }
        }

        public TestResult Test()
        {
            throw new NotImplementedException();
        }

        #endregion

        private void ck_Gac_CheckedChanged(object sender, EventArgs e)
        {
            if (this.ck_Gac.Checked)
            {
                this.txt_AssemblyFileName.Enabled = false;
                this.btn_BrowseAssembly.Enabled = false;
                Assembly sysAssembly = typeof(string).Assembly;
                Type[] types = sysAssembly.GetTypes();
                this.cbo_InputType.Items.Clear();
                foreach (Type type in types)
                {
                    this.cbo_InputType.Items.Add(type.FullName);
                }
            }
            else
            {
                this.txt_AssemblyFileName.Enabled = false;
                this.btn_BrowseAssembly.Enabled = false;
                this.cbo_InputType.Items.Clear();
                if (!string.IsNullOrEmpty(this._CodeRuleComponent.InputAssemblyName))
                {
                    string binFolderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                    string assemblyFilePath = Path.Combine(binFolderPath, this._CodeRuleComponent.InputAssemblyName);
                    Assembly assembly = Assembly.LoadFrom(assemblyFilePath);
                    Type[] types = assembly.GetTypes();
                    foreach (Type type in types)
                    {
                        this.cbo_InputType.Items.Add(type.FullName);
                    }
                }
            }
        }

        private void btn_OK_Click(object sender, EventArgs e)
        {
            this.SaveSettings();
            if(this.UpdateComponentSettingEvent !=null)
            {
                this.UpdateComponentSettingEvent(this._ActivityNode, this._CodeRuleComponent);
            }
            this.Close();
        }

        private void btn_Cancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void cbo_InputType_SelectedIndexChanged(object sender, EventArgs e)
        {
            List<string> externalAssemblies = new List<string>();
            if (this.ck_Gac.Checked == false && (!string.IsNullOrEmpty(this.txt_AssemblyFileName.Text)))
            {
                string binFolderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                string assemblyFilePath = Path.Combine(binFolderPath, this._CodeRuleComponent.InputAssemblyName);
                externalAssemblies.Add(assemblyFilePath);
            }
            if (this.cbo_InputType.SelectedIndex >= 0)
            {
                this._CodeRuleComponent.InputTypeFullName = this.cbo_InputType.Text;
                string codeHeader = CodeRuleWorker.GenerateHeaderCode(this._CodeRuleComponent);
                string codeFooter = CodeRuleWorker.GenerateFooterCode();
                this._CodeFragment.HeaderCode = codeHeader;
                this._CodeFragment.FooterCode = codeFooter;
            }
        }
    }
}
